home *** CD-ROM | disk | FTP | other *** search
- Path: grimsel.zurich.ibm.com!usenet
- From: Keith Whittingham <wgk@zurich.ibm.com>
- Newsgroups: comp.lang.c++
- Subject: Woops!
- Date: Thu, 18 Apr 1996 14:57:05 -0700
- Organization: IBM Zurich Research Laboratory
- Message-ID: <3176BAB1.F52@zurich.ibm.com>
- NNTP-Posting-Host: pine.zurich.ibm.com
- Mime-Version: 1.0
- Content-Type: text/plain; charset=us-ascii
- Content-Transfer-Encoding: 7bit
- X-Mailer: Mozilla 2.01 (Win16; I)
-
- I've just come across a strange bug which was causing a stack
- overflow which might be of interest to you next time you're
- putting together a class. I have my own collection classes -
- "What", you say, "Re-inventing the wheel?" Well yes but, it was
- necessary in order to have built in object persistance, and
- dynamic type checking, and the documentation on every other
- collection class library I've come across is lousy, oh, and of
- course, it was fun.
-
- Anyway the base of the collection is a linked list. When a
- collection, such as a sorted list, is destructed, if destroys
- it's members. This behaviour is inherited from a ABCs Collection
- and Node. The relevant bits look like this...
-
-
- class Node
- {
- public:
- Node() { Nic = 0; }
- virtual ~Node() { if(Nic) delete Nic; }
- private:
- Node *Nic; // Next in chain
- };
-
- class Collection:
- public Node
- {
- public:
- Collection() { Fic = 0; }
- virtual ~Collection() { if(Fic) delete Fic; }
- virtual void Add(Node &n) { /* not relevant code */ }
- private:
- Node *Fic; // First in chain
- };
-
-
- All pretty innocuous stuff really - well... A wolf in lambs
- clothing.
-
- Collection *c = new Collection;
- for(int i = 0; i < 2000; i++)
- {
- c.Add(*new Node);
- }
- delete c; // Bang! (well sometimes)
-
- Why? Well the list of nodes is freed by deleteing the first
- in the chain, that in turn deletes the next and so on. The problem
- is that the call is, effectively recursive and for each node
- in the chain, another return address and another address of 'this'
- is pushed onto the statck. This carries on until the stack
- runs out - as does your program.
-
- The solution - simple have the collection delete the members
- rather than have the chain delete itself...
-
- class Node
- {
- public:
- Node() { Nic = 0; }
- virtual ~Node() { } ///
- private:
- Node *Nic; // Next in chain
- };
-
- class Collection
- {
- public:
- Collection() { Fic = 0; }
- ~Collection()
- {
- Node *n, *Tmp; ///
- n = Fic; ///
- while(n) ///
- { ///
- Tmp = n->Nic; ///
- delete n; ///
- n = Tmp; ///
- } ///
- } ///
- virtual void Add(Node &n) { /* not relevant code */ }
- private:
- Node *Fic; // First in chain
- };
-
-
- Had the statement "delete Nic;" been written Nic::~Node() it
- probably would have been clear from the outset that the
- call was recursive and since it's part of a collection class
- the depth of recursion can not be ascertained. In retrospect
- it's not really a bug, just inappropriate code.
-
- ...OK it's a bug.
-
- --
- Keith Whittingham
- wgk@zurich.ibm.com
-